import lombok.extern.slf4j.Slf4j;

import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Test;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

@Slf4j
public class ZooKeeperTest {

    private static final String zkAddress = "127.0.0.1:2181";

    private static class ClientWatcher implements Watcher {

        private final CountDownLatch latch;

        public ClientWatcher(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void process(WatchedEvent event) {
            log.info("触发watcher");
            if (event.getState() == Event.KeeperState.SyncConnected) {
                log.info("事件状态:{}", event.getState());
                if (event.getType() == Event.EventType.None) {
                    this.latch.countDown();
                    log.info("事件类型:{}", event.getType());
                } else if (event.getType() == Event.EventType.NodeCreated) {
                    log.info("事件类型:{}", event.getType());
                } else if (event.getType() == Event.EventType.NodeChildrenChanged) {
                    log.info("事件类型:{}", event.getType());
                } else if (event.getType() == Event.EventType.NodeDeleted) {
                    log.info("事件类型:{}", event.getType());
                } else if (event.getType() == Event.EventType.NodeDataChanged) {
                    log.info("事件类型:{}", event.getType());
                }
            } else if (event.getState() == Event.KeeperState.Expired) {
                log.info("事件状态:{}", event.getState());
            } else if (event.getState() == Event.KeeperState.SaslAuthenticated) {
                log.info("事件状态:{}", event.getState());
            } else if (event.getState() == Event.KeeperState.ConnectedReadOnly) {
                log.info("事件状态:{}", event.getState());
            } else if (event.getState() == Event.KeeperState.Disconnected) {
                log.info("事件状态:{}", event.getState());
            } else if (event.getState() == Event.KeeperState.AuthFailed) {
                log.info("事件状态:{}", event.getState());
            }
        }
    }

    /**
     * 新增数据
     */
    @Test
    public void test1() throws IOException, InterruptedException, KeeperException {
        CountDownLatch latch = new CountDownLatch(1);
        Watcher watcher = new ClientWatcher(latch);
        ZooKeeper zooKeeper = new ZooKeeper(zkAddress, 2000, watcher);

        if (zooKeeper.getState() == ZooKeeper.States.CONNECTING) {
            log.info("客户端状态:{}", zooKeeper.getState());
            latch.await();
            insert(watcher, zooKeeper);
        } else if (zooKeeper.getState() == ZooKeeper.States.ASSOCIATING) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.AUTH_FAILED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CONNECTED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.NOT_CONNECTED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CLOSED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CONNECTEDREADONLY) {
            log.info("客户端状态:{}", zooKeeper.getState());
        }
    }

    /**
     * 更新数据
     *
     */
    @Test
    public void test2() throws IOException, KeeperException, InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        Watcher watcher = new ClientWatcher(latch);
        ZooKeeper zooKeeper = new ZooKeeper(zkAddress, 2000, watcher);

        if (zooKeeper.getState() == ZooKeeper.States.CONNECTING) {
            log.info("客户端状态:{}", zooKeeper.getState());
            latch.await();
            update(watcher, zooKeeper);
        } else if (zooKeeper.getState() == ZooKeeper.States.ASSOCIATING) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.AUTH_FAILED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CONNECTED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.NOT_CONNECTED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CLOSED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CONNECTEDREADONLY) {
            log.info("客户端状态:{}", zooKeeper.getState());
        }
    }

    /**
     * 删除数据
     *
     */
    @Test
    public void test3() throws IOException, KeeperException, InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        Watcher watcher = new ClientWatcher(latch);
        ZooKeeper zooKeeper = new ZooKeeper(zkAddress, 2000, watcher);

        if (zooKeeper.getState() == ZooKeeper.States.CONNECTING) {
            log.info("客户端状态:{}", zooKeeper.getState());
            latch.await();
            delete(watcher, zooKeeper);
        } else if (zooKeeper.getState() == ZooKeeper.States.ASSOCIATING) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.AUTH_FAILED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CONNECTED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.NOT_CONNECTED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CLOSED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CONNECTEDREADONLY) {
            log.info("客户端状态:{}", zooKeeper.getState());
        }
    }


    /**
     * 查询数据
     *
     */
    @Test
    public void test4() throws IOException, InterruptedException, KeeperException {
        CountDownLatch latch = new CountDownLatch(1);
        Watcher watcher = new ClientWatcher(latch);
        ZooKeeper zooKeeper = new ZooKeeper(zkAddress, 2000, watcher);

        if (zooKeeper.getState() == ZooKeeper.States.CONNECTING) {
            log.info("客户端状态:{}", zooKeeper.getState());
            latch.await();
            getData(watcher, zooKeeper);
        } else if (zooKeeper.getState() == ZooKeeper.States.ASSOCIATING) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.AUTH_FAILED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CONNECTED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.NOT_CONNECTED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CLOSED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CONNECTEDREADONLY) {
            log.info("客户端状态:{}", zooKeeper.getState());
        }
    }

    /**
     * 查询子节点
     */
    @Test
    public void test5() throws IOException, InterruptedException, KeeperException {
        CountDownLatch latch = new CountDownLatch(1);
        Watcher watcher = new ClientWatcher(latch);
        ZooKeeper zooKeeper = new ZooKeeper(zkAddress, 2000, watcher);

        if (zooKeeper.getState() == ZooKeeper.States.CONNECTING) {
            log.info("客户端状态:{}", zooKeeper.getState());
            latch.await();
            getChildren(watcher, zooKeeper);
        } else if (zooKeeper.getState() == ZooKeeper.States.ASSOCIATING) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.AUTH_FAILED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CONNECTED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.NOT_CONNECTED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CLOSED) {
            log.info("客户端状态:{}", zooKeeper.getState());
        } else if (zooKeeper.getState() == ZooKeeper.States.CONNECTEDREADONLY) {
            log.info("客户端状态:{}", zooKeeper.getState());
        }
    }

    private void insert(Watcher watcher, ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
        Stat stat = zooKeeper.exists("/enjoy/bb", watcher);
        log.info("节点信息:{}", stat);
        if (stat == null) {
            String s = zooKeeper.create("/enjoy/bb", "1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            log.info("创建的结果:{}", s);
        } else {
            log.info("该节点已存在");
        }
    }


    private void update(Watcher watcher, ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
        Stat stat = zooKeeper.exists("/enjoy", watcher);
        log.info("节点信息:{}", stat);
        if (stat != null) {
            Stat s = zooKeeper.setData("/enjoy", "bb".getBytes(), -1);
            log.info("更新的结果:{}", s);
        } else {
            log.info("该节点不存在");
        }
    }

    private void delete(Watcher watcher, ZooKeeper zooKeeper) throws KeeperException, InterruptedException {
        Stat stat = zooKeeper.exists("/enjoy", watcher);
        log.info("节点信息:{}", stat);
        if (stat != null) {
            zooKeeper.delete("/enjoy", -1);
            log.info("删除成功!");
        }
    }

    private void getData(Watcher watcher, ZooKeeper zooKeeper) throws KeeperException, InterruptedException {

        Stat stat = new Stat();
        byte[] data = zooKeeper.getData("/enjoy", watcher, stat);

        if (data != null) {
            log.info("数据:{}", new String(data));
        }
        log.info("节点信息:{}", stat);
    }

    private void getChildren(Watcher watcher, ZooKeeper zooKeeper) throws InterruptedException, KeeperException {

        List<String> children = zooKeeper.getChildren("/", watcher);

        if (children != null) {
            log.info("子节点:{}", children);
        }
    }
}
